package com.eastfair.builder.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.util.StrUtil;
//import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.eastfair.boot.request.PageParams;
import com.eastfair.boot.service.SuperServiceImpl;
import com.eastfair.builder.dao.ReportSpaceMapper;
import com.eastfair.builder.dto.ExhibitorDTO;
import com.eastfair.builder.dto.ReportSpaceDTO;
import com.eastfair.builder.entity.Exhibitor;
import com.eastfair.builder.entity.ReportSpace;
import com.eastfair.builder.enumeration.*;
import com.eastfair.builder.exceptioncode.BuilderExceptionCode;
import com.eastfair.builder.service.*;
import com.eastfair.builder.vo.ExhibitorVO;
import com.eastfair.builder.vo.ReportSpaceVO;
import com.eastfair.constant.BusinessConstant;
import com.eastfair.core.base.R;
import com.eastfair.core.context.ContextUtil;
import com.eastfair.core.context.StaticContextUtil;
import com.eastfair.core.exception.BizException;
import com.eastfair.core.exception.NoBackBizException;
import com.eastfair.database.mybatis.typehandler.TypeHandlerUtil;
import com.eastfair.home.dto.ReportBuilderAuditDTO;
import com.eastfair.home.dto.ReportDrawingCategoryAuditDTO;
import com.eastfair.home.dto.ReportSiteAuditDTO;
import com.eastfair.home.dto.ReportSpaceAuditDTO;
import com.eastfair.home.enumeration.*;
import com.eastfair.messagecenter.dto.SmsSendDTO;
import com.eastfair.messagecenter.enumeration.ChannelType;
import com.eastfair.messagecenter.model.SmsContentModel;
import com.eastfair.venueservice.consts.CommonConstants;
import com.eastfair.venueservice.entity.BondConfig;
import com.eastfair.venueservice.entity.CreatCode;
import com.eastfair.venueservice.enumeration.ServiceProviderTypeEnum;
import com.eastfair.venueservice.vo.ServiceProviderVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 业务实现类
 * 报馆记录表
 * </p>
 *
 * @author dq
 * @date 2022-08-06
 */
@Slf4j
@Service
//@DS("#thread.tenant")
public class ReportSpaceServiceImpl extends SuperServiceImpl<ReportSpaceMapper, ReportSpace> implements ReportSpaceService {

    private static final String REPORT_SPACE_NUMBER_PREFIX = "RS";

    private static final String REPORT_SPACE_NUMBER_FIELD = "report_space_number";

    private static final int REPORT_SPACE_NUMBER_LENGTH = 8;

    @Resource
    private ReportSiteService reportSiteService;

    @Resource
    private ReportBuilderService reportBuilderService;

    @Resource
    private ReportDrawingService reportDrawingService;

    @Resource
    private ConstructionPersonnelService constructionPersonnelService;

    @Resource
    private ExhibitorService exhibitorService;

    @Resource
    private BuilderReportSpaceAuditService builderReportSpaceAuditService;

    @Resource
    private BuilderServiceProviderService builderServiceProviderService;

    @Resource
    private BuilderBondConfigService builderBondConfigService;

    @Resource
    private BuilderHomeServiceOrderService builderHomeServiceOrderService;

    @Resource
    private BuilderHomeBondManageService builderHomeBondManageService;

    @Resource
    private ReportSpaceMapper reportSpaceMapper;

    @Resource
    private BuilderMsgService builderMsgService;

    @Resource(name = "threadPoolTaskExecutor")
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;

    /**
     * 处理逻辑删除相关处理
     *
     * @param modelList 实体
     * @return 是否成功
     */
    @Override
    protected R<Boolean> handlerRemoveByIdsOfLogic(Collection<ReportSpace> modelList) {
        modelList.forEach(s -> s.setIsDeleted(BusinessConstant.YES));
        return R.successDef();
    }

    @Override
    protected R<Boolean> handlerSave(ReportSpace model) {
        model.setProjectId(ContextUtil.getProjectId());
        model.setSubsystemId(ContextUtil.getSubSystemId());

        model.setReportSpaceStatus(ReportSpaceReportSpaceStatusEnum.NOT_SUBMIT);
        model.setDrawingAuditStatus(ReportSpaceDrawingAuditStatusEnum.NOT_SUBMIT);
        model.setServiceAuditStatus(ReportSpaceServiceAuditStatusEnum.NOT_SUBMIT);
        model.setHomeAuditStatus(ReportSpaceHomeAuditStatusEnum.NOT_SUBMIT);
        model.setVenueAuditStatus(ReportSpaceVenueAuditStatusEnum.NOT_SUBMIT);
        model.setFinalDrawingAuditStatus(ReportSpaceFinalDrawingAuditStatusEnum.NOT_SUBMIT);
        return R.successDef();
    }

    @Override
    public IPage<ReportSpaceVO> listReportSpaceVOs(PageParams<ReportSpaceDTO> pageParams) {
        log.info("listReportSpaceVOs - 分页查询报馆记录VO, pageParams={}", pageParams);
        Page<ReportSpace> page = pageParams.buildPage();
        ReportSpaceDTO query = pageParams.getModel();
        QueryWrapper<ReportSpace> queryWrapper = createReportSpaceVOQueryWrapper(query);
        IPage<ReportSpaceVO> voPage = reportSpaceMapper.listReportSpaceVOs(page, queryWrapper);
        List<ReportSpaceVO> list = voPage.getRecords();
        if (list == null || list.isEmpty()) {
            return voPage;
        }
        // 查询展馆下的主场，并封装到报馆记录
        List<String> spaceCodeList = list
                .stream()
                .map(ReportSpaceVO::getSpaceCode)
                .collect(Collectors.toList());
        Map<String, List<ServiceProviderVO>> serviceProviderMap
                = builderServiceProviderService.getServiceProviderVOMapByExhibitionId(query.getExhibitionId(), spaceCodeList, ServiceProviderTypeEnum.HOME_SERVICE_PROVIDER.getCode());
        list.forEach(reportSpaceVO -> {
            List<ServiceProviderVO> serviceProviderList = serviceProviderMap.get(reportSpaceVO.getSpaceCode());
            if (serviceProviderList != null && !serviceProviderList.isEmpty()) {
                ServiceProviderVO homeServiceProvider = serviceProviderList.get(0);
                reportSpaceVO.setHomeCourtId(homeServiceProvider.getId());
                reportSpaceVO.setHomeCourtName(homeServiceProvider.getCompanyName());
                String exhibitorContactMobile = reportSpaceVO.getExhibitorContactMobile();
                if (StrUtil.isNotBlank(exhibitorContactMobile)) {
                    String decryptExhibitorContactMobile = TypeHandlerUtil.decrypt(exhibitorContactMobile);
                    reportSpaceVO.setExhibitorContactMobile(decryptExhibitorContactMobile);
                }
            }
        });
        return voPage;
    }

    @Override
    public ReportSpaceVO getReportSpaceVOById(Long id) {
        log.info("getReportSpaceVOById - ID获取报馆详情, id={}", id);
        ReportSpace reportSpace = getById(id);
        if (reportSpace == null) {
            return null;
        }
        return BeanUtil.toBean(reportSpace, ReportSpaceVO.class);
    }

    @Override
    public List<ReportSpace> listByExhibitorId(Long exhibitorId) {
        ReportSpaceDTO query = new ReportSpaceDTO();
        query.setExhibitorId(exhibitorId);
        return listReportSpaces(query);
    }

    @Override
    public List<ReportSpace> listByExhibitorIds(List<Long> exhibitorIds) {
        ReportSpaceDTO query = new ReportSpaceDTO();
        query.setExhibitorIdList(exhibitorIds);
        return listReportSpaces(query);
    }

    @Override
    public Map<Long, ReportSpace> getMapByExhibitorIds(List<Long> exhibitorIds) {
        List<ReportSpace> reportSpaceList = listByExhibitorIds(exhibitorIds);
        Map<Long, ReportSpace> dict = new HashMap<>(16);
        reportSpaceList.forEach(reportSpace -> dict.put(reportSpace.getExhibitorId(), reportSpace));
        return dict;
    }

    @Override
    public List<ReportSpace> listReportSpaces(ReportSpaceDTO query) {
        QueryWrapper<ReportSpace> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .lambda()
                .eq(ReportSpace::getIsDeleted, BusinessConstant.DELETE_NO)
                .eq(query.getExhibitorId() != null, ReportSpace::getExhibitorId, query.getExhibitorId())
                .in(query.getExhibitorIdList() != null && !query.getExhibitorIdList().isEmpty(), ReportSpace::getExhibitorId, query.getExhibitorIdList())
        ;
        return list(queryWrapper);
    }

    @Override
    public ReportSpace getByExhibitorId(Long exhibitorId) {
        log.info("getByExhibitorId - 展商ID查询报馆记录, exhibitorId={}", exhibitorId);
        List<ReportSpace> reportSpacesList = listByExhibitorId(exhibitorId);
        if (reportSpacesList == null || reportSpacesList.isEmpty()) {
            return null;
        }
        return reportSpacesList.get(0);
    }

    @Override
    public ExhibitorVO getShouldEarnestMoneyById(Long id) {
        log.info("getSiteBondById - 报馆id查询展位保证金, id={}", id);
        ReportSpace reportSpace = getById(id);
        if (reportSpace == null) {
            throw BizException.wrap(BuilderExceptionCode.REPORT_SPACE_NOT_EXIST);
        }
        ExhibitorVO exhibitorVO = exhibitorService.getExhibitorVO(reportSpace.getExhibitorId());
        if (exhibitorVO == null) {
            throw BizException.wrap(BuilderExceptionCode.EXHIBITOR_NOT_EXIST);
        }
        // 如果报馆记录为已提交或审核通过，则不可编辑，查询已经设置的保证金
        if (ReportSpaceReportSpaceStatusEnum.APPROVED.eq(reportSpace.getReportSpaceStatus())
                || ReportSpaceReportSpaceStatusEnum.SUBMIT.eq(reportSpace.getReportSpaceStatus())) {
            return exhibitorVO;
        }
        if (exhibitorVO.getHomeId() == null) {
            throw BizException.wrap(-1, "查询保证金失败，未找到负责的主场");
        }
        // 查询主场设置的保证金
        BondConfig bondConfig = builderBondConfigService.getBySiteArea(exhibitorVO.getExhibitionManageId(), exhibitorVO.getHomeId(), exhibitorVO.getSiteArea());
        if (bondConfig == null) {
            throw BizException.wrap(-1, "保证金未设置，请通知主场设置保证金");
        }
        exhibitorVO.setIsEarnestMoneySet(BusinessConstant.YES);
        exhibitorVO.setShouldEarnestMoney(bondConfig.getBondAmount());
        return exhibitorVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ReportSpace saveReportSpace(ReportSpaceDTO saveDTO) {
        log.info("saveReportSpace - 保存报馆记录, saveDTO={}", saveDTO);
        List<ReportSpace> list = listByExhibitorId(saveDTO.getExhibitorId());
        if (list != null && !list.isEmpty()) {
            throw NoBackBizException.wrap(BuilderExceptionCode.REPORT_SPACE_HAS_EXIST.getCode(), "该展位已存在报馆记录");
        }
        // 生成一键报馆编码
        String reportVenueSpaceNumber = CreatCode.creatCode(baseMapper, REPORT_SPACE_NUMBER_FIELD,
                REPORT_SPACE_NUMBER_LENGTH, REPORT_SPACE_NUMBER_PREFIX);
        saveDTO.setReportSpaceNumber(reportVenueSpaceNumber);
        ReportSpace reportSpace = BeanUtil.toBean(saveDTO, ReportSpace.class);
        save(reportSpace);
        // 更新报馆状态为报馆中
        if (saveDTO.getExhibitorId() != null) {
            exhibitorService.updateSiteStatusReporting(saveDTO.getExhibitorId());
        }
        return reportSpace;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateReportSpace(ReportSpaceDTO updateDTO) {
        log.info("updateReportSpace - 更新报馆记录, saveDTO={}", updateDTO);
        ReportSpace reportSpace = BeanUtil.toBean(updateDTO, ReportSpace.class);
        return updateById(reportSpace);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean submitReportSpace(Long reportSpaceId) {
        log.info("submitReportSpace - 提交报馆记录, reportSpaceId={}", reportSpaceId);
        ReportSpace reportSpace = getById(reportSpaceId);
        if (reportSpace == null) {
            throw NoBackBizException.wrap(BuilderExceptionCode.REPORT_SPACE_NOT_EXIST);
        }
        if (ReportSpaceReportSpaceStatusEnum.APPROVED.eq(reportSpace.getReportSpaceStatus())
                || ReportSpaceReportSpaceStatusEnum.SUBMIT.eq(reportSpace.getReportSpaceStatus())) {
            throw NoBackBizException.wrap(BuilderExceptionCode.REPORT_SPACE_CAN_NOT_SUBMIT.getCode(), "报馆当前待审核或已审核通过，不可再提交");
        }
        // 生成报馆展位信息审核数据
        ReportSiteAuditDTO reportSiteAuditDTO = reportSiteService.createAuditByReportSpaceId(reportSpaceId);
        // 生成报馆搭建商信息审核数据
        ReportBuilderAuditDTO reportBuilderAuditDTO = reportBuilderService.createAuditByReportSpaceId(reportSpaceId);
        // 生成报馆图纸分类审核数据
        List<ReportDrawingCategoryAuditDTO> reportDrawingCategoryAuditList = reportDrawingService.createAuditListByReportSpaceId(reportSpaceId);
        // 生成报馆保证金审核数据
        ExhibitorVO exhibitorVO = getShouldEarnestMoneyById(reportSpace.getId());
        // 更新应支付保证金
        updateShouldEarnestMoney(reportSpace, exhibitorVO);
        // 更新报馆记录状态为提交
        updateReportSpaceStatusSubmit(reportSpace);
        ReportSpaceAuditDTO reportSpaceAuditDTO = toReportSpaceAuditDTO(reportSpace);
        reportSpaceAuditDTO.setReportSiteAudit(reportSiteAuditDTO);
        reportSpaceAuditDTO.setReportBuilderAudit(reportBuilderAuditDTO);
        reportSpaceAuditDTO.setReportDrawingCategoryAuditList(reportDrawingCategoryAuditList);
        reportSpaceAuditDTO.setEarnestMoney(exhibitorVO.getShouldEarnestMoney());
        reportSpaceAuditDTO.setIsDouble(exhibitorVO.getIsDouble());
        reportSpaceAuditDTO.setIsPoint(exhibitorVO.getIsPoint());
        // 提交审核到主场
        return builderReportSpaceAuditService.submitReportSpaceAudit(reportSpaceAuditDTO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ReportSpace updateReportSpaceStatusSubmit(ReportSpace reportSpace) {
        Exhibitor exhibitor = exhibitorService.getById(reportSpace.getExhibitorId());
        if (exhibitor == null) {
            throw BizException.wrap(BuilderExceptionCode.EXHIBITOR_NOT_EXIST);
        }
        // 更新最新的展位信息
        reportSpace.setExhibitorId(exhibitor.getId());
        reportSpace.setExhibitorName(exhibitor.getExhibitorName());
        reportSpace.setExhibitorContact(exhibitor.getExhibitorContacts());
        reportSpace.setExhibitorContactMobile(exhibitor.getExhibitorContactsTel());
        reportSpace.setSiteCode(exhibitor.getSiteCode());
        reportSpace.setSiteName(exhibitor.getSiteName());
        reportSpace.setSpaceCode(exhibitor.getSpaceCode());
        reportSpace.setSpaceName(exhibitor.getSpaceName());
        reportSpace.setSiteType(exhibitor.getSiteType().getCode());
        reportSpace.setSiteArea(exhibitor.getSiteArea());
        // 重置审核状态
        reportSpace.setReportSpaceStatus(ReportSpaceReportSpaceStatusEnum.SUBMIT);
        reportSpace.setHomeAuditStatus(ReportSpaceHomeAuditStatusEnum.SUBMIT);
        // 用图纸最终审核状态来判断是否需要重置主场和场馆的图纸审核状态
        if (!ReportSpaceFinalDrawingAuditStatusEnum.APPROVED.eq(reportSpace.getFinalDrawingAuditStatus())) {
            reportSpace.setDrawingAuditStatus(ReportSpaceDrawingAuditStatusEnum.SUBMIT);
            reportSpace.setDrawingAuditOpinion(null);
            reportSpace.setFinalDrawingAuditStatus(ReportSpaceFinalDrawingAuditStatusEnum.SUBMIT);

            // 如果展位需要上传吊点图纸，则需要场馆审核，状态为待审核，如果不是，则场馆审核状态为无需审核
            boolean needVenueAudit = reportDrawingService.getNeedVenueAudit(reportSpace.getId(), exhibitor.getIsDouble(), exhibitor.getIsPoint());
            if (!needVenueAudit) {
                reportSpace.setVenueAuditStatus(ReportSpaceVenueAuditStatusEnum.NOT_NEED_AUDIT);
            } else {
                reportSpace.setVenueAuditStatus(ReportSpaceVenueAuditStatusEnum.SUBMIT);
            }
        }
        if (!ReportSpaceServiceAuditStatusEnum.APPROVED.eq(reportSpace.getServiceAuditStatus())) {
            reportSpace.setServiceAuditStatus(ReportSpaceServiceAuditStatusEnum.SUBMIT);
            reportSpace.setServiceAuditOpinion(null);
            reportSpace.setManageAuditStatus(ReportSpaceManageAuditStatusEnum.SUBMIT);
            reportSpace.setManageAuditOpinion(null);
            reportSpace.setEarnestMoneyAuditStatus(ReportSpaceEarnestMoneyAuditStatusEnum.SUBMIT);
            reportSpace.setEarnestMoneyAuditOpinion(null);
        }
        updateAllById(reportSpace);
        return reportSpace;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateReportSpaceAuditStatus(ReportSpaceDTO reportSpaceDTO) {
        log.info("updateReportSpaceAuditStatus - 更新报馆审核状态, reportSpaceDTO={}", reportSpaceDTO);
        ReportSpace reportSpace = getById(reportSpaceDTO.getId());
        if (reportSpace == null) {
            throw BizException.wrap(BuilderExceptionCode.REPORT_SPACE_NOT_EXIST);
        }
        // 更新报馆审核结果
        reportSpace.setServiceAuditStatus(reportSpaceDTO.getServiceAuditStatus());
        reportSpace.setServiceAuditOpinion(reportSpaceDTO.getServiceAuditOpinion());
        reportSpace.setDrawingAuditStatus(reportSpaceDTO.getDrawingAuditStatus());
        reportSpace.setDrawingAuditOpinion(reportSpaceDTO.getDrawingAuditOpinion());
        reportSpace.setManageAuditStatus(reportSpaceDTO.getManageAuditStatus());
        reportSpace.setManageAuditOpinion(reportSpaceDTO.getManageAuditOpinion());
        reportSpace.setEarnestMoneyAuditStatus(reportSpaceDTO.getEarnestMoneyAuditStatus());
        reportSpace.setEarnestMoneyAuditOpinion(reportSpaceDTO.getEarnestMoneyAuditOpinion());
        reportSpace.setHomeAuditStatus(reportSpaceDTO.getHomeAuditStatus());
        reportSpace.setVenueAuditStatus(reportSpaceDTO.getVenueAuditStatus());
        reportSpace.setFinalDrawingAuditStatus(reportSpaceDTO.getFinalDrawingAuditStatus());
        reportSpace.setReportSpaceStatus(reportSpaceDTO.getReportSpaceStatus());
        updateById(reportSpace);
        // 报馆审核通过馆，更新展位状态为已报馆
        if (ReportSpaceReportSpaceStatusEnum.APPROVED.eq(reportSpaceDTO.getReportSpaceStatus())) {
            exhibitorService.updateSiteStatusHasReported(reportSpace.getExhibitorId());
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateVenueAuditStatus(ReportSpaceDTO reportSpaceDTO) {
        ReportSpace reportSpace = getById(reportSpaceDTO.getId());
        if (reportSpace == null) {
            throw BizException.wrap(BuilderExceptionCode.REPORT_SPACE_NOT_EXIST);
        }
        reportSpace.setVenueAuditStatus(reportSpaceDTO.getVenueAuditStatus());
        reportSpace.setFinalDrawingAuditStatus(reportSpaceDTO.getFinalDrawingAuditStatus());
        reportSpace.setReportSpaceStatus(reportSpaceDTO.getReportSpaceStatus());
        // 更新场馆审核结果
        updateById(reportSpace);
        // 报馆审核通过馆，更新展位状态为已报馆
        if (ReportSpaceReportSpaceStatusEnum.APPROVED.eq(reportSpace.getReportSpaceStatus())) {
            exhibitorService.updateSiteStatusHasReported(reportSpace.getExhibitorId());
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateReportSpaceAuditStatusNotSubmit(Long reportSpaceId) {
        log.info("updateReportSpaceAuditStatusNotSubmit - 报馆取消申请, reportSpaceId={}", reportSpaceId);
        ReportSpace reportSpace = getById(reportSpaceId);
        if (reportSpace == null) {
            throw BizException.wrap(BuilderExceptionCode.REPORT_SPACE_NOT_EXIST);
        }
        if (ReportSpaceDrawingAuditStatusEnum.APPROVED.eq(reportSpace.getDrawingAuditStatus())
                || ReportSpaceDrawingAuditStatusEnum.NOT_APPROVED.eq(reportSpace.getDrawingAuditStatus())) {
            throw NoBackBizException.wrap(BuilderExceptionCode.REPORT_SPACE_CAN_NOT_CANCEL_SUBMIT.getCode(), "主场已审核图纸，不可取消");
        }
        if (ReportSpaceServiceAuditStatusEnum.APPROVED.eq(reportSpace.getServiceAuditStatus())
                || ReportSpaceServiceAuditStatusEnum.NOT_APPROVED.eq(reportSpace.getServiceAuditStatus())) {
            throw NoBackBizException.wrap(BuilderExceptionCode.REPORT_SPACE_CAN_NOT_CANCEL_SUBMIT.getCode(), "主场已审核服务，不可取消");
        }
        reportSpace.setDrawingAuditStatus(ReportSpaceDrawingAuditStatusEnum.NOT_SUBMIT);
        reportSpace.setDrawingAuditOpinion(null);
        reportSpace.setServiceAuditStatus(ReportSpaceServiceAuditStatusEnum.NOT_SUBMIT);
        reportSpace.setServiceAuditOpinion(null);
        reportSpace.setReportSpaceStatus(ReportSpaceReportSpaceStatusEnum.NOT_SUBMIT);
        reportSpace.setEarnestMoneyAuditStatus(ReportSpaceEarnestMoneyAuditStatusEnum.NOT_SUBMIT);
        reportSpace.setEarnestMoneyAuditOpinion(null);
        reportSpace.setManageAuditStatus(ReportSpaceManageAuditStatusEnum.NOT_SUBMIT);
        reportSpace.setManageAuditOpinion(null);
        reportSpace.setHomeAuditStatus(ReportSpaceHomeAuditStatusEnum.NOT_SUBMIT);
        reportSpace.setVenueAuditStatus(ReportSpaceVenueAuditStatusEnum.NOT_SUBMIT);
        reportSpace.setFinalDrawingAuditStatus(ReportSpaceFinalDrawingAuditStatusEnum.NOT_SUBMIT);
        updateAllById(reportSpace);
        return builderReportSpaceAuditService.cancelSubmit(reportSpaceId);
    }

    @Transactional(rollbackFor = Exception.class)
    public boolean updateShouldEarnestMoney(ReportSpace reportSpace, ExhibitorVO exhibitorVO) {
        ExhibitorDTO exhibitorDTO = new ExhibitorDTO();
        exhibitorDTO.setId(reportSpace.getExhibitorId());
        exhibitorDTO.setShouldEarnestMoney(exhibitorVO.getShouldEarnestMoney());
        return exhibitorService.updateShouldEarnestMoney(exhibitorDTO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean removeReportSpaceById(Long id) {
        log.info("removeReportSpaceById - 报馆ID删除报馆记录, id={}", id);
        ReportSpace reportSpace = getById(id);
        if (reportSpace == null) {
            return false;
        }
        // 删除报馆搭建商基本信息
        reportBuilderService.removeByReportSpaceId(id);
        // 删除报馆展位基本信息
        reportSiteService.removeByReportSpaceId(id);
        // 删除报馆图纸
        reportDrawingService.removeByReportSpaceId(id);
        // 删除报馆施工人员
        constructionPersonnelService.removeByReportSpaceId(id);
        // 删除报馆记录
        List<ReportSpace> list = new ArrayList<>();
        list.add(reportSpace);
        removeByIdsOfLogic(list);
        // 取消报馆审核记录
        builderReportSpaceAuditService.cancelSubmit(id);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean removeByExhibitorId(Long exhibitorId) {
        log.info("removeByExhibitorId - 展商展位ID删除报馆信息, exhibitorId={}", exhibitorId);
        ReportSpace reportSpace = getByExhibitorId(exhibitorId);
        if (reportSpace == null) {
            return false;
        }
        // 删除报馆信息
        removeReportSpaceById(reportSpace.getId());
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean removeByExhibitorIdList(List<Long> exhibitorIdList) {
        if (exhibitorIdList == null || exhibitorIdList.isEmpty()) {
            return false;
        }
        exhibitorIdList.forEach(this::removeByExhibitorId);
        return true;
    }

    @Override
    public boolean sendDrawingAuditMsg(Long reportSpaceId) {
        log.info("sendDrawingAuditMsg - 发送图纸审核通过信息, reportSpaceId={}", reportSpaceId);
        ReportSpace reportSpace = getById(reportSpaceId);
        if (reportSpace == null) {
            log.info("无法发送报馆图纸审核信息，报馆信息不存在");
            return false;
        }
        String drawingApprovedTemplate = "报馆号【%s】您所上传图纸，未通过审核，请按照主场要求进行上传";
        String drawingNotApprovedTemplate = "报馆号【%s】您所上传的图纸，已通过审核，请及时缴纳管理费和保证金，避免影响后续入场流程";
        String content = null;
        // 主场图纸审核通过，场馆不需要审核或者审核通过，则发送审核通过的短信
        if (ReportSpaceDrawingAuditStatusEnum.APPROVED.eq(reportSpace.getDrawingAuditStatus())
                && (ReportSpaceVenueAuditStatusEnum.NOT_NEED_AUDIT.eq(reportSpace.getVenueAuditStatus())
                || ReportSpaceVenueAuditStatusEnum.APPROVED.eq(reportSpace.getVenueAuditStatus()))) {
            content = String.format(drawingApprovedTemplate, reportSpace.getReportSpaceNumber());
        }
        // 主场审核图纸不通过，则发送短信
        if (ReportSpaceDrawingAuditStatusEnum.NOT_APPROVED.eq(reportSpace.getDrawingAuditStatus())) {
            content = String.format(drawingNotApprovedTemplate, reportSpace.getReportSpaceNumber());
        }
        // 场馆审核不通过，则发送短信
        if (ReportSpaceVenueAuditStatusEnum.NOT_APPROVED.eq(reportSpace.getVenueAuditStatus())) {
            content = String.format(drawingNotApprovedTemplate, reportSpace.getReportSpaceNumber());
        }
        if (StrUtil.isBlank(content)) {
            log.info("无需发送报馆图纸审核信息, drawingAuditStatus={}, venueAuditStatus={}", reportSpace.getDrawingAuditStatus(), reportSpace.getVenueAuditStatus());
            return false;
        }
        SmsSendDTO smsSendDTO = new SmsSendDTO();
        smsSendDTO.setBusinessType(BusinessConstant.BUSINESS_COMMON);
        smsSendDTO.setChannelType(ChannelType.SMS);
        smsSendDTO.setBusinessId(ContextUtil.getTrace());
        smsSendDTO.setSystemScene(StaticContextUtil.getProjectSystemScene());
        // 封装内容
        Map<String, Object> contentMap = new HashMap<>(16);
        contentMap.put("content", content);
        SmsContentModel smsContentModel = new SmsContentModel();
        smsContentModel.setContentMap(contentMap);
        smsSendDTO.setSmsContentModelList(Collections.singletonList(smsContentModel));
        // 发送用户的手机号
        smsSendDTO.setTeamId(reportSpace.getBuilderId());
        // 发送时间
        smsSendDTO.setIsSendNow(BusinessConstant.YES);
        // 发送短信
        builderMsgService.sendSmsMsg(smsSendDTO);
        return true;
    }

    @Override
    public void asyncSendDrawingAuditMsg(Long reportSpaceId) {
        threadPoolTaskExecutor.execute(() -> sendDrawingAuditMsg(reportSpaceId));
    }

    @Override
    public boolean sendDrawingAuditMsg(ReportSpaceAuditDTO reportSpaceAudit) {
        log.info("sendDrawingAuditMsg - 发送图纸审核通过信息, reportSpaceAudit={}", reportSpaceAudit);
        if (reportSpaceAudit == null) {
            log.info("无法发送报馆图纸审核信息，报馆信息不存在");
            return false;
        }
        String drawingApprovedTemplate = "报馆号【%s】您所上传的图纸，已通过审核，请及时缴纳管理费和保证金，避免影响后续入场流程";
        String drawingNotApprovedTemplate = "报馆号【%s】您所上传图纸，未通过审核，请按照主场要求进行上传";
        String content = null;
        // 主场图纸审核通过，场馆不需要审核或者审核通过，则发送审核通过的短信
        if (ReportSpaceDrawingAuditStatusEnum.APPROVED.eq(reportSpaceAudit.getDrawingAuditStatus().getCode())
                && (ReportSpaceVenueAuditStatusEnum.NOT_NEED_AUDIT.eq(reportSpaceAudit.getVenueAuditStatus())
                || ReportSpaceVenueAuditStatusEnum.APPROVED.eq(reportSpaceAudit.getVenueAuditStatus()))) {
            content = String.format(drawingApprovedTemplate, reportSpaceAudit.getReportSpaceNumber());
        }
        // 主场审核图纸不通过，则发送短信
        if (ReportSpaceDrawingAuditStatusEnum.NOT_APPROVED.eq(reportSpaceAudit.getDrawingAuditStatus().getCode())) {
            content = String.format(drawingNotApprovedTemplate, reportSpaceAudit.getReportSpaceNumber());
        }
        // 场馆审核不通过，则发送短信
        if (ReportSpaceVenueAuditStatusEnum.NOT_APPROVED.eq(reportSpaceAudit.getVenueAuditStatus())) {
            content = String.format(drawingNotApprovedTemplate, reportSpaceAudit.getReportSpaceNumber());
        }
        if (StrUtil.isBlank(content)) {
            log.info("无需发送报馆图纸审核信息, drawingAuditStatus={}, venueAuditStatus={}", reportSpaceAudit.getDrawingAuditStatus(), reportSpaceAudit.getVenueAuditStatus());
            return false;
        }
        SmsSendDTO smsSendDTO = new SmsSendDTO();
        smsSendDTO.setBusinessType(BusinessConstant.BUSINESS_COMMON);
        smsSendDTO.setChannelType(ChannelType.SMS);
        smsSendDTO.setBusinessId(ContextUtil.getTrace());
        smsSendDTO.setSystemScene(StaticContextUtil.getProjectSystemScene());
        // 封装内容
        Map<String, Object> contentMap = new HashMap<>(16);
        contentMap.put("content", content);
        SmsContentModel smsContentModel = new SmsContentModel();
        smsContentModel.setContentMap(contentMap);
        smsSendDTO.setSmsContentModelList(Collections.singletonList(smsContentModel));
        // 发送用户的手机号
        ServiceProviderVO builder = builderServiceProviderService.getById(reportSpaceAudit.getBuilderId());
        Set<String> mobileSet = new HashSet<>();
        mobileSet.add(builder.getPrincipalMobile());
        smsSendDTO.setMobileList(mobileSet);
        // 发送时间
        smsSendDTO.setIsSendNow(BusinessConstant.YES);
        // 发送短信
        builderMsgService.sendSmsMsg(smsSendDTO);
        return true;
    }

    @Override
    public void asyncSendDrawingAuditMsg(ReportSpaceAuditDTO reportSpaceAudit) {
        threadPoolTaskExecutor.execute(() -> sendDrawingAuditMsg(reportSpaceAudit));
    }

    /**
     * ReportSpace TO ReportSpaceAuditDTO
     *
     * @param reportSpace ReportSpace
     * @return ReportSpaceAuditDTO
     */
    private ReportSpaceAuditDTO toReportSpaceAuditDTO(ReportSpace reportSpace) {
        List<String> ignoreProperties = new ArrayList<>();
        Collections.addAll(ignoreProperties, CommonConstants.COMMON_IGNORE_PROPERTIES);
        Collections.addAll(ignoreProperties, "reportSpaceStatus",
                "drawingAuditStatus", "serviceAuditStatus", "homeAuditStatus", "venueAuditStatus", "finalDrawingAuditStatus");
        String[] ignoreArray = new String[ignoreProperties.size()];
        ignoreProperties.toArray(ignoreArray);
        CopyOptions copyOptions = CopyOptions
                .create()
                .setIgnoreProperties(ignoreArray);
        ReportSpaceAuditDTO reportSpaceAuditDTO = BeanUtil.toBean(reportSpace, ReportSpaceAuditDTO.class, copyOptions);
        // 报馆ID
        reportSpaceAuditDTO.setReportSpaceId(reportSpace.getId());
        // 补全报馆审核的状态值
        completeReportSpaceAuditStatus(reportSpace, reportSpaceAuditDTO);
        return reportSpaceAuditDTO;
    }

    public void completeReportSpaceAuditStatus(ReportSpace reportSpace, ReportSpaceAuditDTO reportSpaceAuditDTO) {
        // 报馆状态
        ReportSpaceAuditReportSpaceStatusEnum reportSpaceStatus = ReportSpaceAuditReportSpaceStatusEnum.get(reportSpace.getReportSpaceStatus().getCode());
        reportSpaceAuditDTO.setReportSpaceStatus(reportSpaceStatus);
        // 主场审核状态
        reportSpaceAuditDTO.setHomeAuditStatus(reportSpace.getHomeAuditStatus().getCode());
        // 图纸最终审核状态
        ReportSpaceAuditFinalDrawingAuditStatusEnum finalDrawingAuditStatus = ReportSpaceAuditFinalDrawingAuditStatusEnum.get(reportSpace.getFinalDrawingAuditStatus().getCode());
        reportSpaceAuditDTO.setFinalDrawingAuditStatus(finalDrawingAuditStatus);
        // 主场图纸审核状态
        ReportSpaceAuditDrawingAuditStatusEnum drawingAuditStatus = ReportSpaceAuditDrawingAuditStatusEnum.get(reportSpace.getDrawingAuditStatus().getCode());
        reportSpaceAuditDTO.setDrawingAuditStatus(drawingAuditStatus);
        if (ReportSpaceAuditDrawingAuditStatusEnum.SUBMIT.eq(drawingAuditStatus)) {
            reportSpaceAuditDTO.setDrawingAuditOpinion(null);
            reportSpaceAuditDTO.setDrawingAuditUserId(null);
            reportSpaceAuditDTO.setDrawingAuditUserName(null);
        }
        // 场馆图纸审核状态
        reportSpaceAuditDTO.setVenueAuditStatus(reportSpace.getVenueAuditStatus().getCode());
        // 服务审核状态
        ReportSpaceAuditServiceAuditStatusEnum serviceAuditStatus = ReportSpaceAuditServiceAuditStatusEnum.get(reportSpace.getServiceAuditStatus().getCode());
        reportSpaceAuditDTO.setServiceAuditStatus(serviceAuditStatus);
        if (ReportSpaceAuditServiceAuditStatusEnum.SUBMIT.eq(serviceAuditStatus)) {
            reportSpaceAuditDTO.setServiceAuditOpinion(null);
            reportSpaceAuditDTO.setServiceAuditUserId(null);
            reportSpaceAuditDTO.setServiceAuditUserName(null);
        }
        // 管理费审核状态
        ReportSpaceAuditManageAuditStatusEnum manageAuditStatus = ReportSpaceAuditManageAuditStatusEnum.get(reportSpace.getManageAuditStatus().getCode());
        reportSpaceAuditDTO.setManageAuditStatus(manageAuditStatus);
        // 保证金审核状态
        ReportSpaceAuditEarnestMoneyAuditStatusEnum earnestMoneyAuditStatus = ReportSpaceAuditEarnestMoneyAuditStatusEnum.get(reportSpace.getEarnestMoneyAuditStatus().getCode());
        reportSpaceAuditDTO.setEarnestMoneyAuditStatus(earnestMoneyAuditStatus);
    }

    /**
     * 生成ReportSpaceVO的查询.
     *
     * @param query ReportSpaceDTO.
     * @return QueryWrapper.
     */
    private QueryWrapper<ReportSpace> createReportSpaceVOQueryWrapper(ReportSpaceDTO query) {
        QueryWrapper<ReportSpace> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .eq("rsp.is_deleted", BusinessConstant.DELETE_NO)
                .eq(query.getExhibitionId() != null, "rsp.exhibition_id", query.getExhibitionId())
                .eq(query.getBuilderId() != null, "rsp.builder_id", query.getBuilderId())
                .like(StrUtil.isNotBlank(query.getExhibitorName()), "rsp.exhibitor_name", query.getExhibitorName())
                .like(StrUtil.isNotBlank(query.getSiteName()), "rsp.site_name", query.getSiteName())
                .like(StrUtil.isNotBlank(query.getSpaceName()), "rsp.space_name", query.getSpaceName())
                .eq(query.getDrawingAuditStatus() != null, "rsp.drawing_audit_status", query.getDrawingAuditStatus())
                .eq(query.getServiceAuditStatus() != null, "rsp.service_audit_status", query.getServiceAuditStatus())
                .eq(query.getReportSpaceStatus() != null, "rsp.report_space_status", query.getReportSpaceStatus())
        ;
        return queryWrapper;
    }

}
